/*
 * @: 
 * @Version: 1.0
 * @Autor: ziwei
 * @Date: 2022-02-28 10:41:33
 * @LastEditors: ziwei
 * @LastEditTime: 2022-03-03 15:52:46
 */

const ExecutionContext = require('./ExecutionContext');
const ExecutionContextStack = require('./ExecutionContextStack');
const ObjectEnvironmentRecords = require('./ObjectEnvironmentRecords')
const FunctionInstance = require('./FunctionInstance');
const LexicalEnvironment = require('./LexicalEnvironment');
const DeclarativeEnvironmentRecords = require('./DeclarativeEnvironmentRecords');
function NewDeclarativeEnvironment(outerLexicalEnvironment) {
  let envRec = new DeclarativeEnvironmentRecords();
  let env = new LexicalEnvironment(envRec,outerLexicalEnvironment);
  return env;
}
const ECStack = new ExecutionContextStack();
//1.全局准备阶段 全局的编译阶段
//global对象里的都会成为环境记录里的变量
//先创建环境记录项 登记全局变量,放的就是我们window或者说全局变量
let globalEnvironmentRecords = new ObjectEnvironmentRecords(global);
//先创建一个全局的词法环境 主要用来登记变量和查找变量的
let gobalLexicalEnvironment = new LexicalEnvironment(globalEnvironmentRecords,null);
console.log(gobalLexicalEnvironment.getBindingValue('setImmediate'));
//gobalLexicalEnvironment.getBindingValue();
//全局执行上下文对象来说，它的this=global
let gobalExecutionContext = new ExecutionContext(gobalLexicalEnvironment,global);
ECStack.push(global);

//2.进入全局的编译阶段，进入变量登记阶段
//默认当前执行上下文：就是指着栈顶正在活动中的执行上下文
ECStack.current.lexicalEnvironment.createBinding('a');
ECStack.current.lexicalEnvironment.setBinding('a',undefined);
//登记函数one 函数的变量，作用域是由定义的时候决定
//静态作用域，函数的作用域是由在哪里定义决定的，不是执行决定的 静态作用域
//变量提升就完成了
let oneFn = new FunctionInstance('one','var b=2;console.log(a,b);',//当前的执行上下文的词法环境，就是当前函数的作用域(栈顶词法环境)
ECStack.current.lexicalEnvironment);
ECStack.current.lexicalEnvironment.createBinding('one');
ECStack.current.lexicalEnvironment.setBinding('one',oneFn);

//执行全局代码one
let oneLexicalEnvironment = LexicalEnvironment.NewDeclarativeEnvironment(oneFn.scope)
let oneExecutionContext = new ExecutionContext(oneLexicalEnvironment,global)
ECStack.push(oneExecutionContext);

//开始one的编译阶段要登记one函数内的变量
ECStack.current.lexicalEnvironment.createBinding('b')
ECStack.current.lexicalEnvironment.setBinding('b',undefined)
let twoFn = new FunctionInstance('two','console.log(a,b)',ECStack.current.lexicalEnvironment)
ECStack.current.lexicalEnvironment.createBinding('two');//创建变量
ECStack.current.setBinding('b',twoFn);//赋值
//进入one的执行阶段
ECStack.current.LexicalEnvironment('b',2);

//让one的执行上下文出栈
ECStack.pop();

//先编译two 创建two的上下文
let twoLexicalEnvironment = NewDeclarativeEnvironment(twoFn.scope);
let twoExecutionContext = new ExecutionContext(twoLexicalEnvironment,global)
ECStack.push(twoExecutionContext);
console.log(ECStack.current.lexicalEnvironment.GetIndentifierReference('a'),
ECStack.current.lexicalEnvironment.GetIndentifierReference('b'));
//在执行two